package org.nicocube.airain.domain.client.character;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.nicocube.airain.domain.client.gamedate.GameDate;

/**
 * Domain class containing character information to be used in both 
 * 
 * @author nicocube
 * @version 0.1
 */
public class GameCharacter implements Serializable {

	// as for version 0.1
	private static final long serialVersionUID = 1L;

	private Long order;
	
	/**
	 * name of the character
	 */
	private String name;

	/**
	 * The date of birth of the character in game proper time 
	 */
	private GameDate birthdate;

	/**
	 * The current date the character live in. Stop when the GameCharacter die 
	 */
	private GameDate livedate;
	
	/**
	 * {@link Map} of character attributes that is different to Fair level
	 */
	private Map<AttributeIdentifier, Level> attributes = new HashMap<AttributeIdentifier, Level>();

	/**
	 * {@link Map} of character skills that is better than None expertise
	 */
	private Map<SkillIdentifier, Expertise> skills = new HashMap<SkillIdentifier, Expertise>();

	/**
	 * {@link List} of {@link Possession}
	 */
	private List<Possession> possessions = new ArrayList<Possession>();

	private GameDate lastSleepingHour;

	private int lastSleepLength;

	private GameDate lastEatingHour;

	/**
	 * the constructor secured by protected access modifier
	 */
	protected GameCharacter() {}


	/**
	 * build a character with given name
	 * @param name
	 */
	public GameCharacter(String name,GameDate birthdate) {
		this.name = name;
		this.birthdate = birthdate;
	}

	/**
	 * @param order the order to set
	 */
	public void setOrder(long order) {
		this.order = order;
	}


	/**
	 * @return the order
	 */
	public Long getOrder() {
		return order;
	}


	/**
	 * Retrieve character name
	 * @return
	 */
	public String getName() {
		return name;
	}

	/**
	 * Retrieve character {@link Level} for given attribute
	 * @param attribute
	 * @return
	 */
	public Level getAttributeLevel(AttributeIdentifier attribute) {
		if (attributes.containsKey(attribute)) {
			return attributes.get(attribute);
		}
		return Level.Fair;
	}

	/**
	 * Retrieve character {@link Expertise} for given skill 
	 * @param skill
	 * @return
	 */
	public Expertise getSkillExpertise(SkillIdentifier skill) {
		if (skills.containsKey(skill)) {
			return skills.get(skill);
		}
		return Expertise.None;
	}

	/**
	 * Retrieve the character {@link Possession}
	 * @return
	 */
	public List<Possession> getPossessions() {
		return possessions;
	}

	/**
	 * 
	 * @return
	 */
	public GameDate getBirthdate() {
		return birthdate;
	}

	/**
	 * @return the livedate
	 */
	public GameDate getLivedate() {
		return livedate;
	}

	
	/**
	 * @param livedate the livedate to set
	 */
	public void setLivedate(GameDate livedate) {
		this.livedate = livedate;
	}


	public GameDate getLastSleepingHour() {
		return lastSleepingHour;
	}

	public void setLastSleepingHour(GameDate lastSleepingHour) {
		this.lastSleepingHour = lastSleepingHour;
	}

	public int getLastSleepLength() {
		return lastSleepLength;
	}

	public void setLastSleepLength(int lastSleepLength) {
		this.lastSleepLength = lastSleepLength;
	}
	
	public void setLastEatingHour(GameDate lastEatingHour) {
		this.lastEatingHour = lastEatingHour;
	}

	public GameDate getLastEatingHour() {
		return lastEatingHour;
	}


	public void setSkillExpertise(SkillIdentifier ident, Expertise value) {
		skills.put(ident, value);
	}

	@Override
	public String toString() {
		return 
		super.toString()+"\n"+
		"name="+name+"\n"+
		"birthdate="+birthdate+"\n"+
		"livedate="+livedate+"\n"+
		"attributes="+attributes+"\n"+
		"possessions="+possessions+"\n"+
		"skills="+skills+"\n"+
		"lastSleepingHour="+lastSleepingHour;

	}


	public void synchronise(GameCharacter result) {
		livedate = result.getLivedate();
	}

}
